﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIIV.Data;
using SIIV.Business.Exceptions;

namespace SIIV.Business
{
    public class MuestraBusiness
    {
        public List<Muestra> ObtenerMuestras(int idProtocolo)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.Muestras.Include("Animal").Include("TiposDeMuestra").Include("Analisis").Where(m => m.IdProtocolo.Equals(idProtocolo)).ToList();
            } 
        }

        public void CrearMuestra(int idProtocolo, int idUsuario, int idAnimal, short idTipoDeMuestra)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                model.AddToMuestras(new Muestra()
                {
                    Fecha = DateTime.Now,
                    IdAnimal = idAnimal,
                    IdProtocolo = idProtocolo,
                    IdTipoDeMuestra = idTipoDeMuestra,
                    IdUsuario = idUsuario
                });
                model.SaveChanges();
            }
        }

        public void ActualizarMuestra(int idProtocolo,int idMuestra, int idAnimal, short idTipoDeMuestra)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (!model.Muestras.Any(m => m.IdProtocolo.Equals(idProtocolo) && m.IdAnimal.Equals(idAnimal) && m.IdTipoDeMuestra.Equals(idTipoDeMuestra)))
                {
                    Muestra muestra = model.Muestras.Single(m => m.IdMuestra.Equals(idMuestra));
                    muestra.IdAnimal = idAnimal;
                    muestra.IdTipoDeMuestra = idTipoDeMuestra;

                    model.SaveChanges();
                }
                else
                {
                    throw new FunctionalException("Ya existe una muestra de este tipo para este animal en este protocolo.");
                }
            }
        }

        public void EliminarMuestra(int idMuestra)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                model.Muestras.DeleteObject(model.Muestras.Single(m => m.IdMuestra.Equals(idMuestra)));
                model.SaveChanges();
            }
        }

        public List<Analisis> ObtenerAnalisis(int idMuestra)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.Analisis1.Include("TipoDeAnalisis").Include("EstadoDeAnalisis").Include("HistoriasDeAnalisis").Where(a => a.IdMuestra.Equals(idMuestra)).ToList();
            }
        }

        public List<Analisis> ObtenerAnalisis(int idVeterinario, int? idAnimal)
        {
            return new AnalisisBusiness().ObtenerAnalisis(idVeterinario, idAnimal);
        }

        public List<TipoDeMuestra> ObtenerTiposDeMuestras()
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.TiposDeMuestras.ToList();
            }
        }

        public void AgregarAnalisis(int idMuestraSeleccionada, short idTipoDeAnalisis, string observaciones, int idUsuario)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (!model.Analisis1.Any(a => a.IdMuestra.Equals(idMuestraSeleccionada) && a.IdTipoDeAnalisis.Equals(idTipoDeAnalisis)))
                {
                    Muestra muestra = model.Muestras.Single(m => m.IdMuestra.Equals(idMuestraSeleccionada));
                    Analisis analisis = new Analisis()
                    {
                        Fecha = DateTime.Now,
                        IdEstadoDeAnalisis = (short)SIIV.Business.AnalisisBusiness.EstadosDeAnalisis.Inicial,
                        IdTipoDeAnalisis = idTipoDeAnalisis
                    };
                    analisis.HistoriasDeAnalisis = new System.Data.Objects.DataClasses.EntityCollection<HistoriaDeAnalisis>();
                    analisis.HistoriasDeAnalisis.Add(new HistoriaDeAnalisis()
                    {
                        Descripcion = observaciones,
                        Fecha = DateTime.Now,
                        IdUsuario = idUsuario
                    });
                    muestra.Analisis.Add(analisis);
                    model.SaveChanges();
                }
                else
                {
                    throw new FunctionalException("Ya existe un análisis de este tipo para la muestra seleccionada.");
                }
            }
        }

        public void ActualizarAnalisis(int idAnalisis, short idTipoDeAnalisis, short idEstadoDeAnalisis, string observaciones, int idUsuario)
        {
            AnalisisBusiness analisisBusiness = new AnalisisBusiness();
            analisisBusiness.ActualizarAnalisis(idAnalisis, idTipoDeAnalisis, idEstadoDeAnalisis, observaciones, idUsuario);
        }

        public Protocolo CrearProtocolo(int idVeterinario)
        {
            ProtocoloBusiness protocoloBusiness = new ProtocoloBusiness();
            return protocoloBusiness.CrearProtocolo(idVeterinario);
        }

        public List<AnalisisxMuestras> ObtenerTiposDeAnalisis(short idTipoDeMuestra)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.AnalisisxMuestras.Where(a => a.IdTipoMuestra.Equals(idTipoDeMuestra)).OrderBy(t => t.Analisis).ToList();
            }
        }

        public List<Protocolo> CargarProtocolos(int idVeterinario)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.Protocolos.Where(p => p.IdVeterinario.Equals(idVeterinario)).ToList();
            }
        }

        public void GuardarMuestra(int idProtocolo, int idAnimal, short idTipoDeMuestra, int idUsuario)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (!model.Muestras.Any(m => m.IdProtocolo.Equals(idProtocolo) && m.IdAnimal.Equals(idAnimal) && m.IdTipoDeMuestra.Equals(idTipoDeMuestra)))
                {
                    model.AddToMuestras(new Muestra()
                    {
                        Fecha = DateTime.Now,
                        IdAnimal = idAnimal,
                        IdProtocolo = idProtocolo,
                        IdTipoDeMuestra = idTipoDeMuestra,
                        IdUsuario = idUsuario
                    });
                    model.SaveChanges();
                }
                else
                {
                    throw new FunctionalException("Ya existe una muestra de este tipo para este animal en este protocolo.");
                }
            }
        }

        public void EliminarResultadoAnalisis(int idResultadoAnalisis)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                model.ResultadosDeAnalisis.DeleteObject(model.ResultadosDeAnalisis.Single(r => r.IdResultadoDeAnalisis.Equals(idResultadoAnalisis)));
                model.SaveChanges();
            }
        }

        public void GuardarResultadoAnalisis(int idAnalisis, short idTipoDeIndicador, string valor, int unidad)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (!model.ResultadosDeAnalisis.Any(a => a.IdAnalisis.Equals(idAnalisis) && a.IdIndicador.Equals(idTipoDeIndicador)))
                {
                    model.ResultadosDeAnalisis.AddObject(new ResultadoDeAnalisis() { IdAnalisis = idAnalisis, IdIndicador = idTipoDeIndicador, Valor = valor, Unidad = unidad, Fecha = DateTime.Now });
                    model.SaveChanges();
                }
                else
                {
                    throw new FunctionalException("Ya existe un indicador de este tipo para este análisis.");
                }
            }
        }

        public List<Unidad> ObtenerUnidades()
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.Unidads.ToList();
            }        
        }

        public List<IndicadoresXanalisis> ObtenerIndicadores(short idTipoDeAnalisis)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.IndicadoresXanalisis.Where(i => i.IdTipoAnalisis.Equals(idTipoDeAnalisis)).OrderBy(i => i.Indicador).ToList();
            }
        }

        public List<ResultadoDeAnalisis> ObtenerResultadosAnalisis(int idAnalisisSeleccionado)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.ResultadosDeAnalisis.Include("Indicador").Include("Unidade").Where(r => r.IdAnalisis.Equals(idAnalisisSeleccionado)).ToList();
            }
        }

        public object ObtenerProyeccionEnfermedadesFuturas(int idAnimal, DateTime fechaInicial, DateTime fechaFinal)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.ExecuteFunction("sp_SistInteligente", new System.Data.Objects.ObjectParameter[] { new System.Data.Objects.ObjectParameter("IdAnimal", idAnimal), new System.Data.Objects.ObjectParameter("FechaIni", fechaInicial), new System.Data.Objects.ObjectParameter("FechaFin", fechaFinal) });
            }
        }

        public void EliminarProtocolo(int idProtocolo)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                model.Protocolos.DeleteObject(model.Protocolos.Single(p => p.IdProtocolo.Equals(idProtocolo)));
                model.SaveChanges();
            }
        }

        public Indicador ObtenerIndicador(int idIndicador)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.Indicadores.Single(i => i.IdIndicador.Equals(idIndicador));
            }
        }

        public void EliminarAnalisis(int idMuestraSeleccionada)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                var analisis = model.Analisis1.Where(i => i.IdMuestra.Equals(idMuestraSeleccionada));
                foreach (var a in analisis)
                {
                    model.DeleteObject(a);
                }
                model.SaveChanges();
            }
        }

        public List<v_Administracion> ObtenerHistorial()
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.v_Administracion.OrderByDescending(v => v.Fecha_Ingreso_Prot).ToList();
            }
        }
    }
}
